From: kaf24@firebug.cl.cam.ac.uk Date: Fri, 12 May 2006 14:17:21 +0000 (+0100) Subject: Fix the cirrus vga model to not leak memory when switching between X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~16047^2~79 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=17af31bde615d3655b2659319d3d8d6b6e3b3e73;p=xen.git Fix the cirrus vga model to not leak memory when switching between initial vga mode and linear framebuffer. When creating device model, the vga memory is allocated through xc_domain_memory_increase_reservation(), however, when switch to use linear framebuffer, we didn't free that memory, and re-allocate the vga memory through set_mm_mapping(), that caused memory leak. Now it is changed to just using qemu_malloc when create device model, and free that memory when switch to linear framebuffer. After unset_vram_mapping(), the old memory pointer should be unmapped; after set_vram_mapping(), the old memory should be freed. Signed-off-by: Yunhong Jiang --- diff --git a/tools/ioemu/hw/cirrus_vga.c b/tools/ioemu/hw/cirrus_vga.c index 80fd981df7..8f3ac73d26 100644 --- a/tools/ioemu/hw/cirrus_vga.c +++ b/tools/ioemu/hw/cirrus_vga.c @@ -272,7 +272,8 @@ typedef struct CirrusVGAState { int last_hw_cursor_y_end; int real_vram_size; /* XXX: suppress that */ CPUWriteMemoryFunc **cirrus_linear_write; - int set_mapping; + unsigned long map_addr; + unsigned long map_end; } CirrusVGAState; typedef struct PCICirrusVGAState { @@ -2543,12 +2544,12 @@ static int unset_vram_mapping(unsigned long begin, unsigned long end) static void * set_vram_mapping(unsigned long addr, unsigned long end) {} static int unset_vram_mapping(unsigned long addr, unsigned long end) {} #endif +extern int vga_accelerate; /* Compute the memory access functions */ static void cirrus_update_memory_access(CirrusVGAState *s) { unsigned mode; - extern int vga_accelerate; if ((s->sr[0x17] & 0x44) == 0x44) { goto generic_io; @@ -2563,18 +2564,21 @@ static void cirrus_update_memory_access(CirrusVGAState *s) mode = s->gr[0x05] & 0x7; if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { - if (vga_accelerate && s->cirrus_lfb_addr && s->cirrus_lfb_end) { - if (!s->set_mapping) { - void * vram_pointer; - s->set_mapping = 1; - vram_pointer = set_vram_mapping(s->cirrus_lfb_addr ,s->cirrus_lfb_end); - if (!vram_pointer){ + if ( vga_accelerate && s->cirrus_lfb_addr && s->cirrus_lfb_end ) { + if (!s->map_addr) { + void *vram_pointer, *old_vram; + + vram_pointer = + set_vram_mapping(s->cirrus_lfb_addr ,s->cirrus_lfb_end); + if (!vram_pointer) { fprintf(stderr, "NULL vram_pointer\n"); - } else - { - vga_update_vram((VGAState *)s, vram_pointer, + } else { + old_vram = vga_update_vram((VGAState *)s, vram_pointer, VGA_RAM_SIZE); + qemu_free(old_vram); } + s->map_addr = s->cirrus_lfb_addr; + s->map_end = s->cirrus_lfb_end; } } s->cirrus_linear_write[0] = cirrus_linear_mem_writeb; @@ -2583,13 +2587,19 @@ static void cirrus_update_memory_access(CirrusVGAState *s) } else { generic_io: if (vga_accelerate && s->cirrus_lfb_addr && s->cirrus_lfb_end) { - if(s->set_mapping) { + if(s->map_addr) { int error; - s->set_mapping = 0; + void *old_vram = NULL; + error = unset_vram_mapping(s->cirrus_lfb_addr, s->cirrus_lfb_end); if (!error) - vga_update_vram((VGAState *)s, NULL, VGA_RAM_SIZE); + old_vram = + vga_update_vram((VGAState *)s, NULL, VGA_RAM_SIZE); + + if (old_vram) + munmap(old_vram, s->map_addr - s->map_end); + s->map_addr = s->map_end = 0; } } @@ -3184,6 +3194,12 @@ static void cirrus_pci_lfb_map(PCIDevice *d, int region_num, s->cirrus_linear_io_addr); s->cirrus_lfb_addr = addr; s->cirrus_lfb_end = addr + VGA_RAM_SIZE; + + if ( vga_accelerate && s->map_addr && + (s->cirrus_lfb_addr != s->map_addr) && + (s->cirrus_lfb_end != s->map_end)) + fprintf(logfile, "cirrus vga map change while on lfb mode\n"); + cpu_register_physical_memory(addr + 0x1000000, 0x400000, s->cirrus_linear_bitblt_io_addr); } diff --git a/tools/ioemu/hw/pc.c b/tools/ioemu/hw/pc.c index 474b1de4f4..40cbc826a4 100644 --- a/tools/ioemu/hw/pc.c +++ b/tools/ioemu/hw/pc.c @@ -385,7 +385,6 @@ void pc_init(uint64_t ram_size, int vga_ram_size, int boot_device, char buf[1024]; int ret, linux_boot, initrd_size, i, nb_nics1; PCIBus *pci_bus; - extern void * shared_vram; linux_boot = (kernel_filename != NULL); @@ -512,14 +511,14 @@ void pc_init(uint64_t ram_size, int vga_ram_size, int boot_device, if (cirrus_vga_enabled) { if (pci_enabled) { pci_cirrus_vga_init(pci_bus, - ds, shared_vram, ram_size, + ds, NULL, ram_size, vga_ram_size); } else { - isa_cirrus_vga_init(ds, shared_vram, ram_size, + isa_cirrus_vga_init(ds, NULL, ram_size, vga_ram_size); } } else { - vga_initialize(pci_bus, ds, shared_vram, ram_size, + vga_initialize(pci_bus, ds, NULL, ram_size, vga_ram_size); } diff --git a/tools/ioemu/hw/vga.c b/tools/ioemu/hw/vga.c index c04befca3b..2d9e6449bf 100644 --- a/tools/ioemu/hw/vga.c +++ b/tools/ioemu/hw/vga.c @@ -1946,11 +1946,11 @@ void vga_bios_init(VGAState *s) } +/* when used on xen environment, the vga_ram_base is not used */ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, unsigned long vga_ram_offset, int vga_ram_size) { int i, j, v, b; - extern void* shared_vram; for(i = 0;i < 256; i++) { v = 0; @@ -1979,11 +1979,7 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, /* qemu's vga mem is not detached from phys_ram_base and can cause DM abort * when guest write vga mem, so allocate a new one */ -#if defined(__i386__) || defined(__x86_64__) - s->vram_ptr = shared_vram; -#else s->vram_ptr = qemu_malloc(vga_ram_size); -#endif check_sse2(); s->vram_shadow = qemu_malloc(vga_ram_size+TARGET_PAGE_SIZE+1); if (s->vram_shadow == NULL) @@ -2090,12 +2086,14 @@ int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, return 0; } -int vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size) +void *vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size) { + uint8_t *old_pointer; + if (s->vram_size != vga_ram_size) { fprintf(stderr, "No support to change vga_ram_size\n"); - return -1; + return NULL; } if ( !vga_ram_base ) @@ -2104,15 +2102,16 @@ int vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size) if (!vga_ram_base) { fprintf(stderr, "reallocate error\n"); - return -1; + return NULL; } } /* XXX lock needed? */ memcpy(vga_ram_base, s->vram_ptr, vga_ram_size); + old_pointer = s->vram_ptr; s->vram_ptr = vga_ram_base; - return 0; + return old_pointer; } /********************************************************/ diff --git a/tools/ioemu/hw/vga_int.h b/tools/ioemu/hw/vga_int.h index 1789df51e6..5a116f58ac 100644 --- a/tools/ioemu/hw/vga_int.h +++ b/tools/ioemu/hw/vga_int.h @@ -165,6 +165,6 @@ void vga_draw_cursor_line_32(uint8_t *d1, const uint8_t *src1, unsigned int color0, unsigned int color1, unsigned int color_xor); -int vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size); +void *vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size); extern const uint8_t sr_mask[8]; extern const uint8_t gr_mask[16]; diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 6b60df6d4b..54ec0967fc 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -147,12 +147,6 @@ int repeat_key = 1; TextConsole *vga_console; CharDriverState *serial_hds[MAX_SERIAL_PORTS]; int xc_handle; -unsigned long *vgapage_array; -unsigned long *freepage_array; -unsigned long free_pages; -void *vtop_table; -unsigned long toptab; -unsigned long vgaram_pages; /***********************************************************/ /* x86 ISA bus support */ @@ -2454,32 +2448,6 @@ static uint8_t *signal_stack; #include -#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER) -#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) - -#ifdef __i386__ -#define _LEVEL_3_ 0 -#else -#define _LEVEL_3_ 1 -#endif - -#if _LEVEL_3_ -#define L3_PROT (_PAGE_PRESENT) -#define L1_PAGETABLE_ENTRIES 512 -#else -#define L1_PAGETABLE_ENTRIES 1024 -#endif - -inline int -get_vl2_table(unsigned long count, unsigned long start) -{ -#if _LEVEL_3_ - return ((start + (count << PAGE_SHIFT)) >> L3_PAGETABLE_SHIFT) & 0x3; -#else - return 0; -#endif -} - /* FIXME Flush the shadow page */ int unset_mm_mapping(int xc_handle, uint32_t domid, @@ -2584,10 +2552,8 @@ int main(int argc, char **argv) int serial_device_index; char qemu_dm_logfilename[64]; const char *loadvm = NULL; - unsigned long nr_pages, extra_pages, ram_pages, *page_array; - xc_dominfo_t info; + unsigned long nr_pages, *page_array; extern void *shared_page; - extern void *shared_vram; #if !defined(CONFIG_SOFTMMU) /* we never want that malloc() uses mmap() */ @@ -3045,29 +3011,10 @@ int main(int argc, char **argv) /* init the memory */ phys_ram_size = ram_size + vga_ram_size + bios_size; - ram_pages = ram_size/PAGE_SIZE; -#if defined(__i386__) || defined(__x86_64__) - vgaram_pages = (vga_ram_size -1) / PAGE_SIZE + 1; - free_pages = vgaram_pages / L1_PAGETABLE_ENTRIES; - extra_pages = vgaram_pages + free_pages; -#else - /* Test vga acceleration later */ - extra_pages = 0; -#endif + nr_pages = ram_size/PAGE_SIZE; xc_handle = xc_interface_open(); - xc_domain_getinfo(xc_handle, domid, 1, &info); - - nr_pages = info.nr_pages + extra_pages; - - if ( xc_domain_setmaxmem(xc_handle, domid, - (nr_pages) * PAGE_SIZE/1024 ) != 0) - { - fprintf(logfile, "set maxmem returned error %d\n", errno); - exit(-1); - } - if ( (page_array = (unsigned long *) malloc(nr_pages * sizeof(unsigned long))) == NULL) { @@ -3075,24 +3022,16 @@ int main(int argc, char **argv) exit(-1); } - if (xc_domain_memory_increase_reservation(xc_handle, domid, - extra_pages , 0, 0, NULL) != 0) - { - fprintf(logfile, "increase reservation returned error %d\n", errno); - exit(-1); - } - #if defined(__i386__) || defined(__x86_64__) if ( xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages ) { fprintf(logfile, "xc_get_pfn_list returned error %d\n", errno); exit(-1); } - if ( (phys_ram_base = xc_map_foreign_batch(xc_handle, domid, PROT_READ|PROT_WRITE, page_array, - ram_pages - 1)) == 0 ) + nr_pages - 1)) == 0 ) { fprintf(logfile, "xc_map_foreign_batch returned error %d\n", errno); exit(-1); @@ -3100,31 +3039,11 @@ int main(int argc, char **argv) shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, PROT_READ|PROT_WRITE, - page_array[ram_pages - 1]); - - vgapage_array = &page_array[nr_pages - vgaram_pages]; - - if ( (shared_vram = xc_map_foreign_batch(xc_handle, domid, - PROT_READ|PROT_WRITE, - vgapage_array, - vgaram_pages)) == 0) - { - fprintf(logfile, - "xc_map_foreign_batch vgaram returned error %d\n", errno); - exit(-1); - } - - memset(shared_vram, 0, vgaram_pages * PAGE_SIZE); - toptab = page_array[ram_pages] << PAGE_SHIFT; - - vtop_table = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, - PROT_READ|PROT_WRITE, - page_array[ram_pages]); + page_array[nr_pages - 1]); - freepage_array = &page_array[nr_pages - extra_pages]; #elif defined(__ia64__) - if ( xc_ia64_get_pfn_list(xc_handle, domid, page_array, 0, ram_pages) - != ram_pages ) + if ( xc_ia64_get_pfn_list(xc_handle, domid, page_array, 0, nr_pages) + != nr_pages) { fprintf(logfile, "xc_ia64_get_pfn_list returned error %d\n", errno); exit(-1); @@ -3133,7 +3052,7 @@ int main(int argc, char **argv) if ( (phys_ram_base = xc_map_foreign_batch(xc_handle, domid, PROT_READ|PROT_WRITE, page_array, - ram_pages)) == 0 ) + nr_pages)) == 0 ) { fprintf(logfile, "xc_map_foreign_batch returned error %d\n", errno); exit(-1); @@ -3141,7 +3060,7 @@ int main(int argc, char **argv) if ( xc_ia64_get_pfn_list(xc_handle, domid, page_array, - ram_pages + (GFW_SIZE >> PAGE_SHIFT), 1) != 1 ) + nr_pages + (GFW_SIZE >> PAGE_SHIFT), 1) != 1 ) { fprintf(logfile, "xc_ia64_get_pfn_list returned error %d\n", errno); exit(-1);